package com.example.wowangz.redis;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Redis工具类
 *
 * @author 王振【wosen.wang@transn.com】
 * @version 2017-06-06 15:32
 */
public class RedisUtil {

    // jedis连接池
    private static JedisPool pool = null;

    private RedisUtil() {

    }

    public static JedisPool getPool(){
        return pool;
    }

    /**
     * 根据redis的相关配置初始化redis
     * config   redis连接池默认配置
     * timeout 超时时间默认100秒
     * block 连接redis的区域块 默认第0块
     * port 连接redis的端口6379
     *
     * @param host     redis所在机器的ip
     * @param password 连接redis的密码
     */
    public static void initRedisByConfig(String host, String password) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(10000);
        config.setMaxIdle(2000);
        config.setMaxWaitMillis(1000 * 100);
        config.setTestOnBorrow(true);
        initRedisByConfig(config, host, password, 6379, 0, 100000);
    }

    /**
     * 根据redis的相关配置初始化redis
     *
     * @param config   redis连接池配置 比如可配置最大连接数、空闲状态个数、最大等待时间，详见redis包下redis.clients.jedis.JedisPoolConfig
     * @param host     redis所在机器的ip
     * @param password 连接redis的密码
     * @param port     连接redis的端口
     * @param block    连接redis的区域块
     * @param timeout  超时时间
     */
    public static void initRedisByConfig(JedisPoolConfig config, String host, String password, int port, int block, int timeout) {
        pool = new JedisPool(config, host, port, timeout, password, block);
    }

    /**
     * 根据redis的相关配置初始化redis
     * timeout 超时时间默认100秒
     *
     * @param config   redis连接池配置 比如可配置最大连接数、空闲状态个数、最大等待时间，详见redis包下redis.clients.jedis.JedisPoolConfig
     * @param host     redis所在机器的ip
     * @param password 连接redis的密码
     * @param port     连接redis的端口
     * @param block    连接redis的区域块
     */
    public static void initRedisByConfig(JedisPoolConfig config, String host, String password, int port, int block) {
        initRedisByConfig(config, host, password, port, block, 100000);
    }

    /**
     * 根据redis的相关配置初始化redis
     * timeout 超时时间默认100秒
     * block 连接redis的区域块 默认第0块
     *
     * @param config   redis连接池配置 比如可配置最大连接数、空闲状态个数、最大等待时间，详见redis包下redis.clients.jedis.JedisPoolConfig
     * @param host     redis所在机器的ip
     * @param password 连接redis的密码
     * @param port     连接redis的端口
     */
    public static void initRedisByConfig(JedisPoolConfig config, String host, String password, int port) {
        initRedisByConfig(config, host, password, port, 0, 100000);
    }

    /**
     * 根据redis的相关配置初始化redis
     * timeout 超时时间默认100秒
     * block 连接redis的区域块 默认第0块
     * port 连接redis的端口6379
     *
     * @param config   redis连接池配置 比如可配置最大连接数、空闲状态个数、最大等待时间，详见redis包下redis.clients.jedis.JedisPoolConfig
     * @param host     redis所在机器的ip
     * @param password 连接redis的密码
     */
    public static void initRedisByConfig(JedisPoolConfig config, String host, String password) {
        initRedisByConfig(config, host, password, 6379, 0, 100000);
    }

    /**
     * <p>通过key获取储存在redis中的value</p>
     * <p>并释放连接</p>
     *
     * @param key
     * @return 成功返回value 失败返回null
     */
    public static String get(String key) {
        String value = null;
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            value = jedis.get(key);
        } catch (Exception e) {

        } finally {
            returnResource(jedis);
        }
        return value;
    }

    /**
     * 返还到连接池
     *
     * @param jedis
     */
    public static void returnResource(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }

    /**
     * <p>向redis存入key和value,并释放连接资源</p>
     * <p>如果key已经存在 则覆盖</p>
     *
     * @param key
     * @param value
     * @return 成功 返回OK 失败返回 0
     */
    public static String set(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.set(key, value);
        } catch (Exception e) {
            return "0";
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * <p>删除指定的key,也可以传入一个包含key的数组</p>
     *
     * @param keys 一个key  也可以使 string 数组
     * @return 返回删除成功的个数
     */
    public static Long del(String... keys) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.del(keys);
        } catch (Exception e) {
            return 0L;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * <p>通过key向指定的value值追加值</p>
     *
     * @param key
     * @param str
     * @return 成功返回 添加后value的长度 失败 返回 添加的 value 的长度  异常返回0L
     */
    public static Long append(String key, String str) {
        Jedis jedis = null;
        Long res = null;
        try {
            jedis = pool.getResource();
            res = jedis.append(key, str);
        } catch (Exception e) {
            return 0L;
        } finally {
            returnResource(jedis);
        }
        return res;
    }

    /**
     * <p>判断key是否存在</p>
     *
     * @param key
     * @return true OR false
     */
    public static Boolean exists(String key) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.exists(key);
        } catch (Exception e) {
            return false;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * <p>nx==> not exist</p>
     * <p>将 key 的值设为 value，当且仅当 key 不存在</p>
     * <p>若给定的 key 已经存在，则 SETNX 不做任何动作。 </p>
     *
     * @param key
     * @param value
     * @return 成功返回1 如果存在 和 发生异常 返回 0
     */
    public static Long setnx(String key, String value) {
        Jedis jedis = null;
        try {
            jedis = pool.getResource();
            return jedis.setnx(key, value);
        } catch (Exception e) {
            return 0L;
        } finally {
            returnResource(jedis);
        }
    }

    /**
     * <p>设置key value并制定这个键值的有效期</p>
     *
     * @param key
     * @param value
     * @param seconds 单位:秒
     * @return 成功返回OK 失败和异常返回null
     */
    public static String setex(String key, String value, int seconds) {
        Jedis jedis = null;
        String res = null;
        try {
            jedis = pool.getResource();
            res = jedis.setex(key, seconds, value);
        } catch (Exception e) {

        } finally {
            returnResource(jedis);
        }
        return res;
    }

    /**
     * <p>设置key的值,并返回一个旧值</p>
     *
     * @param key
     * @param value
     * @return 旧值 如果key不存在 则返回null
     */
    public static String getset(String key, String value) {
        Jedis jedis = null;
        String res = null;
        try {
            jedis = pool.getResource();
            res = jedis.getSet(key, value);
        } catch (Exception e) {

        } finally {
            returnResource(jedis);
        }
        return res;
    }
}
